from piston.handler import BaseHandler, AnonymousBaseHandler
from piston.utils import rc, require_mime, require_extended

from models import Object, World, TerrainModifier
from assets.models import Asset

from django.db import IntegrityError

from django.forms import ModelForm
from piston.utils import validate

#==============================================================================
#Microsecond support!
from django.core.serializers.json import DjangoJSONEncoder
DjangoJSONEncoder.TIME_FORMAT = TIME_FORMAT = "%H:%M:%S.%f"

#==[ForeignKey Support]=========================================================
def SetFields(object, attrs):
  for field in object._meta.get_all_field_names():
    f = object._meta.get_field(field)
    ft = type(f).__name__
    if ft == "ForeignKey":
      try:
        oo =  f.rel.to.objects.get(**attrs[field])
        setattr(object, field, oo)
      except f.rel.to.DoesNotExist:
        print f.rel.to.__name__+".DoesNotExist", attrs[field]
        return False
    elif ft == "AutoField":
      pass
    elif field in attrs:
      setattr(object, field, attrs[field])
  return True

def Create(klass, request, *args, **kwargs):
  cn = klass.__class__.__name__  
  try:
    attrs = klass.flatten_dict(request.data)
  except: # TODO
    print cn+":create flatten_dict() failed with", request.data
    return rc.BAD_REQUEST
  
  object = klass.__class__.model()
  
  if not SetFields(object, attrs):
    print cn+":create SetFields() failed with", attrs
    return rc.BAD_REQUEST 
      
  try:
    object.save()
  except IntegrityError:
    print cn+":create object.save() failed with", attrs
    return rc.BAD_REQUEST
  return rc.CREATED
#===============================================================================          

class WorldForm(ModelForm):
   class Meta:
		model = World


class AssetHandler(BaseHandler):
    model = Asset
    fields = ('id', 'format', 'dependencies')

    @classmethod
    def resource_uri(self, i=None):
        id = i.id if i else 'id'
        return ('assets', [id,])

      
class ObjectHandler(BaseHandler):
    model = Object
    #fields = ('name', ('world', ('id',)), 'x', 'y', 'z', 'stamp', ('asset', ('id',)))
    fields = ('id', 'name', 'x', 'y', 'z', 'stamp', ('asset', ('id',)), 'state', 'm11', 'm12', 'm13', 'm21', 'm22', 'm23', 'm31', 'm32', 'm33')

    @classmethod
    def resource_uri(self, i=None):
        id = i.id if i else 'id'
        return ('objects', [id,])
        
    def create(self, request, *args, **kwargs):
      return Create(self, request, *args, **kwargs)


class ModifierHandler(BaseHandler):
    model = TerrainModifier
    fields = ('id', 'type', 'typeData', 'x', 'y', 'z', 'rad', 'stamp', 'state', )

    #@classmethod
    #def resource_uri(self, data):
    #    return ('modifiers', [str(data.id), ])
        
    @classmethod
    def resource_uri(self, i=None):
      id = i.id if i else 'id'    
      return ('modifiers', [id, ])
        
    def create(self, request, *args, **kwargs):
      return Create(self, request, *args, **kwargs)


class WorldHandler(BaseHandler):
    #allowed_methods = ('GET', 'POST', 'PUT', 'DELETE',)
    model = World
    
    @classmethod
    def resource_uri(self, i=None):
        id = i.id if i else 'id'
        return ('worlds', [id,])
    
    def read(self, request, id=None):        
        if id:
            objs = Object.objects.filter(world=id)
            if 'stamp' in request.GET:
              objs = objs.filter(stamp__gt=request.GET['stamp'])
            else:
              objs = objs.exclude(state='D')
            return objs
        else:
            return World.objects.all()
        
    '''      
    @validate(WorldForm, 'PUT')
    def update(self, request, id):
      try: 
        world = World.objects.get(id=id)
      except World.DoesNotExist:
        return rc.NOT_HERE
      form = WorldForm(request.POST, instance=world)
      if form.is_valid():
         #form.save()
         #return rc.ALL_OK
         return form.save()
      else:    
        return rc.BAD_REQUEST
    '''   
    ''' 
    def delete(self, request):
      print request
      if 'id' in request.POST:
        try: 
          world = World.objects.get(id=int(request.POST['id']))
        except World.DoesNotExist:
          return rc.NOT_HERE
        world.delete()
        return rc.DELETED
      else:    
        return rc.BAD_REQUEST
    '''  
'''
class AnonymousBlogpostHandler(AnonymousBaseHandler):
    """
    Anonymous entrypoint for blogposts.
    """
    model = Blogpost
    fields = ('id', 'title', 'content', 'created_on')

    @classmethod
    def resource_uri(self):
        return ('blogposts', [ 'format', ])

class BlogpostHandler(BaseHandler):
    """
    Authenticated entrypoint for blogposts.
    """
    model = Blogpost
    anonymous = AnonymousBlogpostHandler
    fields = ('title', 'content', ('author', ('username',)), 
              'created_on', 'content_length')
    
    def read(self, title=None):
        """
        Returns a blogpost, if `title` is given,
        otherwise all the posts.
        
        Parameters:
         - `title`: The title of the post to retrieve.
        """
        base = Blogpost.objects
        
        if title:
            return base.get(title=title)
        else:
            return base.all()
    
    def content_length(self, blogpost):
        return len(blogpost.content)
        
    @require_extended
    def create(self, request):
        """
        Creates a new blogpost.
        """
        attrs = self.flatten_dict(request.POST)

        if self.exists(**attrs):
            return rc.DUPLICATE_ENTRY
        else:
            post = Blogpost(title=attrs['title'], 
                            content=attrs['content'],
                            author=request.user)
            post.save()
            
            return post
    
    @classmethod
    def resource_uri(self):
        return ('blogposts', [ 'format', ])
'''
